#include <android/log.h>
#include "com_smp_dsandroidtester_ds_DSNativeWrapper.h"
#include "../../../DataStructure/DSInterface/DSInterface.h"

#define ENABLE_LOGGING

#ifdef ENABLE_LOGGING
	#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "DSNative", __VA_ARGS__)
	#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "DSNative", __VA_ARGS__)
	#define LOGI(...) __android_log_print(ANDROID_LOG_INFO   , "DSNative", __VA_ARGS__)
	#define LOGW(...) __android_log_print(ANDROID_LOG_WARN   , "DSNative", __VA_ARGS__)
	#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "DSNative", __VA_ARGS__)
#else
	#define LOGV(...)
	#define LOGD(...)
	#define LOGI(...)
	#define LOGW(...)
	#define LOGE(...)
#endif

#define BOOL_TO_STR(BOOL_VARIABLE) (BOOL_VARIABLE==0 ? "false" : "true")


JNIEXPORT jlong JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_createIntArrayStack(JNIEnv *env, jobject clazz, jint a_nSize, jboolean a_bConcurrent) {
	int nSize = (int)a_nSize;
	bool bConcurrent = (bool)a_bConcurrent;

	DSHandle* phDS = new DSHandle;
	setDefaultIntegerArrayStackHandle(phDS, nSize, bConcurrent);

	bool bSucceed = createDS(phDS);
	LOGD("createIntArrayStack : %s", BOOL_TO_STR(bSucceed));

	return (jlong)phDS;
}

JNIEXPORT jlong JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_createIntLinkedStack(JNIEnv *env, jobject clazz, jint a_nMaxSize, jboolean a_bConcurrent) {
	int nSize = (int)a_nMaxSize;
	bool bConcurrent = (bool)a_bConcurrent;

	DSHandle* phDS = new DSHandle;
	setDefaultIntegerLinkedStackHandle(phDS, nSize, bConcurrent);

	bool bSucceed = createDS(phDS);
	LOGD("createIntLinkedStack : %s", BOOL_TO_STR(bSucceed));

	return (jlong)phDS;

}

JNIEXPORT jlong JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_createIntArrayQueue(JNIEnv *env, jobject clazz, jint a_nSize, jboolean a_bConcurrent) {
	int nSize = (int)a_nSize;
	bool bConcurrent = (bool)a_bConcurrent;

	DSHandle* phDS = new DSHandle;
	setDefaultIntegerArrayQueueHandle(phDS, nSize, bConcurrent);

	bool bSucceed = createDS(phDS);
	LOGD("createIntArrayQueue : %s", BOOL_TO_STR(bSucceed));

	return (jlong)phDS;
}

JNIEXPORT jlong JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_createIntLinkedQueue(JNIEnv *env, jobject clazz, jint a_nMaxSize, jboolean a_bConcurrent) {
	int nSize = (int)a_nMaxSize;
	bool bConcurrent = (bool)a_bConcurrent;

	DSHandle* phDS = new DSHandle;
	setDefaultIntegerLinkedQueueHandle(phDS, nSize, bConcurrent);

	bool bSucceed = createDS(phDS);
	LOGD("createIntLinkedQueue : %s", BOOL_TO_STR(bSucceed));

	return (jlong)phDS;
}

JNIEXPORT jboolean JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_destroyDS(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	bool bSucceed = destroyDS(phDS);
	LOGD("destroyDS : %s", BOOL_TO_STR(bSucceed));

	delete phDS;

	return bSucceed;
}

JNIEXPORT void JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_pushIntStack(JNIEnv *env, jobject clazz, jlong a_pBindedHandle, jint a_nData) {
	LOGD("pushIntStack : pushed data : %d", a_nData);
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	pushIntStack(phDS, a_nData);
}

JNIEXPORT jint JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_popIntStack(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jint poppedValue = (jint) popIntStack(phDS);
	LOGD("popIntStack : popped data : %d", poppedValue);
	return poppedValue;
}

JNIEXPORT jboolean JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_canPushIntStack(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jboolean bPushAvailable = (jboolean) canPushIntStack(phDS);
	LOGD("canPushIntStack : %s", BOOL_TO_STR(bPushAvailable));

	return bPushAvailable;
}

JNIEXPORT jboolean JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_canPopIntStack(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jboolean bPopAvailable = (jboolean) canPopIntStack(phDS);
	LOGD("canPopIntStack : %s", BOOL_TO_STR(bPopAvailable));

	return bPopAvailable;
}

JNIEXPORT jint JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_getDataCountIntStack(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jint dataCount = (jint) getDataCountIntStack(phDS);
	LOGD("getDataCountIntStack : %d", dataCount);

	return dataCount;
}

JNIEXPORT void JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_offerIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle, jint a_nData) {
	LOGD("offerIntQueue : offered data :  %d", a_nData);
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	offerIntQueue(phDS, a_nData);
}

JNIEXPORT jint JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_pollIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jint polledValue = (jint) pollIntQueue(phDS);
	LOGD("offerIntQueue : polled data :  %d", polledValue);

	return polledValue;
}

JNIEXPORT jint JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_peekIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jint peekedValue = (jint) peekIntQueue(phDS);
	LOGD("offerIntQueue : peeked data :  %d", peekedValue);

	return peekedValue;
}

JNIEXPORT jboolean JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_canOfferIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jboolean bOfferAvailable = (jboolean) canOfferIntQueue(phDS);
	LOGD("canOfferIntQueue : %s", BOOL_TO_STR(bOfferAvailable));

	return bOfferAvailable;
}

JNIEXPORT jboolean JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_canPollIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jboolean bPollAvailable = (jboolean) canPollIntQueue(phDS);
	LOGD("canPollIntQueue : %s", BOOL_TO_STR(bPollAvailable));

	return bPollAvailable;
}

JNIEXPORT jint JNICALL Java_com_smp_dsandroidtester_ds_DSNativeWrapper_getDataCountIntQueue(JNIEnv *env, jobject clazz, jlong a_pBindedHandle) {
	DSHandle* phDS = (DSHandle*)a_pBindedHandle;

	jint dataCount = (jint) getDataCountIntQueue(phDS);
	LOGD("getDataCountIntQueue : %d", dataCount);

	return dataCount;
}
